// Package sqlite - database migrations
package sqlite

import (
	"database/sql"
	"fmt"

	"github.com/steveyegge/beads/internal/storage/sqlite/migrations"
)

// Migration represents a single database migration
type Migration struct {
	Name string
	Func func(*sql.DB) error
}

// migrations is the ordered list of all migrations to run
// Migrations are run in order during database initialization
var migrationsList = []Migration{
	{"dirty_issues_table", migrations.MigrateDirtyIssuesTable},
	{"external_ref_column", migrations.MigrateExternalRefColumn},
	{"composite_indexes", migrations.MigrateCompositeIndexes},
	{"closed_at_constraint", migrations.MigrateClosedAtConstraint},
	{"compaction_columns", migrations.MigrateCompactionColumns},
	{"snapshots_table", migrations.MigrateSnapshotsTable},
	{"compaction_config", migrations.MigrateCompactionConfig},
	{"compacted_at_commit_column", migrations.MigrateCompactedAtCommitColumn},
	{"export_hashes_table", migrations.MigrateExportHashesTable},
	{"content_hash_column", migrations.MigrateContentHashColumn},
	{"external_ref_unique", migrations.MigrateExternalRefUnique},
	{"source_repo_column", migrations.MigrateSourceRepoColumn},
	{"repo_mtimes_table", migrations.MigrateRepoMtimesTable},
	{"child_counters_table", migrations.MigrateChildCountersTable},
	{"blocked_issues_cache", migrations.MigrateBlockedIssuesCache},
}

// MigrationInfo contains metadata about a migration for inspection
type MigrationInfo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

// ListMigrations returns list of all registered migrations with descriptions
// Note: This returns ALL registered migrations, not just pending ones (all are idempotent)
func ListMigrations() []MigrationInfo {
	result := make([]MigrationInfo, len(migrationsList))
	for i, m := range migrationsList {
		result[i] = MigrationInfo{
			Name:        m.Name,
			Description: getMigrationDescription(m.Name),
		}
	}
	return result
}

// getMigrationDescription returns a human-readable description for a migration
func getMigrationDescription(name string) string {
	descriptions := map[string]string{
		"dirty_issues_table":           "Adds dirty_issues table for auto-export tracking",
		"external_ref_column":          "Adds external_ref column to issues table",
		"composite_indexes":            "Adds composite indexes for better query performance",
		"closed_at_constraint":         "Adds constraint ensuring closed issues have closed_at timestamp",
		"compaction_columns":           "Adds compaction tracking columns (compacted_at, compacted_at_commit)",
		"snapshots_table":              "Adds snapshots table for issue history",
		"compaction_config":            "Adds config entries for compaction",
		"compacted_at_commit_column":   "Adds compacted_at_commit to snapshots table",
		"export_hashes_table":          "Adds export_hashes table for idempotent exports",
		"content_hash_column":          "Adds content_hash column for collision resolution",
		"external_ref_unique":          "Adds UNIQUE constraint on external_ref column",
		"source_repo_column":           "Adds source_repo column for multi-repo support",
		"repo_mtimes_table":            "Adds repo_mtimes table for multi-repo hydration caching",
		"child_counters_table":         "Adds child_counters table for hierarchical ID generation with ON DELETE CASCADE",
		"blocked_issues_cache":         "Adds blocked_issues_cache table for GetReadyWork performance optimization (bd-5qim)",
	}
	
	if desc, ok := descriptions[name]; ok {
		return desc
	}
	return "Unknown migration"
}

// RunMigrations executes all registered migrations in order with invariant checking
func RunMigrations(db *sql.DB) error {
	snapshot, err := captureSnapshot(db)
	if err != nil {
		return fmt.Errorf("failed to capture pre-migration snapshot: %w", err)
	}

	for _, migration := range migrationsList {
		if err := migration.Func(db); err != nil {
			return fmt.Errorf("migration %s failed: %w", migration.Name, err)
		}
	}

	if err := verifyInvariants(db, snapshot); err != nil {
		return fmt.Errorf("post-migration validation failed: %w", err)
	}

	return nil
}
